package com.seed.core.query;

@SuppressWarnings("unchecked")
public class SeedUpdate {
//    public static <T> void update(Seed seed, Map<String, Declared> declareds, T data) {
//        T validData = getValidData(seed, declareds, data);
//        List<? extends OnUpdateListener> listeners = seed.getOnUpdate();
//        if(listeners != null) {
//            for(OnUpdateListener listener: listeners) listener.onUpdate(validData);
//        }
//
//        if(data instanceof Row row) {
//            updateForRow(seed, declareds, row);
//        } else {
//            updateForObject(seed, declareds, data);
//        }
//    }
//
//    public static <T> void updateBatch(Seed seed, Map<String, Declared> declareds, List<T> data) {
//        if(data.isEmpty()) return;
//
//        if(isPlain(declareds)) {
//            List<T> list = new ArrayList<>();
//            for(T t: data) {
//                T validData = getValidData(seed, declareds, t);
//                List<? extends OnSaveListener> listeners = seed.getOnSave();
//                if(listeners != null) {
//                    for(OnSaveListener listener: listeners) listener.onSave(validData);
//                }
//                list.add(t);
//            }
//
//            T t = data.get(0);
//            if(t instanceof Row) {
//                List<Row> rows = list.stream().map(e -> (Row) e).toList();
//                Db.updateBatchById(seed.getTableName(), rows);
//            } else {
//                BaseMapper<T> baseMapper = Mappers.ofEntityClass((Class<T>) t.getClass());
//                for(T entity: list) baseMapper.update(entity);
//            }
//        } else {
//            for (T t: data) update(seed, declareds, t);
//        }
//    }
//
//    public static void updateForRow(Seed seed, Map<String, Declared> declareds, Row self) {
//        for(Map.Entry<String, Declared> entry: declareds.entrySet()) {
//            String crossOrColumn = entry.getKey();
//            String fieldName = StrUtil.toCamelCase(crossOrColumn);
//            Declared value = entry.getValue();
//            PropertyType propertyType = value.getType();
//            switch (propertyType) {
//                case belongsTo -> {
//                    BelongsTos belongsTo = (BelongsTos) value.getProperty();
//                    Row target = (Row) self.remove(fieldName);
////                    if(belongsTo.getExtraType() != ExtraType.code) {
////                        String selfField = StrUtil.toCamelCase(belongsTo.inferSelfColumn());
////                        String targetField = StrUtil.toCamelCase(belongsTo.inferTargetColumn());
////                        self.set(selfField, target == null ? null : target.get(targetField));
////                    }
//                    String selfField = StrUtil.toCamelCase(belongsTo.inferSelfColumn());
//                    String targetField = StrUtil.toCamelCase(belongsTo.inferTargetColumn());
//                    self.set(selfField, target == null ? null : target.get(targetField));
//                }
//                case hasOne -> {
////                    HasOnes hasOne = (HasOnes) value.getProperty();
////                    Seed targetSeed = hasOne.targetSeed();
////                    String targetTableName = targetSeed.getTableName();
////                    String inferSelfColumn = hasOne.inferSelfColumn();
////                    String inferTargetColumn = hasOne.inferTargetColumn();
////                    String selfField = StrUtil.toCamelCase(inferSelfColumn);
////                    String targetField = StrUtil.toCamelCase(inferTargetColumn);
////                    Row target = (Row) self.remove(fieldName);
////
////                    QueryCondition queryCondition = hasOne.getQueryCondition(self, null);
////                    Row one = DbChain.table(targetTableName).where(queryCondition).one();
////                    if(target == null) {
////                        removeOne(hasOne, one);
////                        return;
////                    }
////
////                    Object targetId = target.get(Const.ID);
////                    if(targetId == null) { // 新增加的数据
////                        removeOne(hasOne, one);
////
//////                        if(hasOne.getExtraType() != ExtraType.code) target.set(targetField, self.get(selfField));
////                        target.set(targetField, self.get(selfField));
////                        SeedSave.save(targetSeed, value, target);
////                        return;
////                    }
////
////                    if(one == null) {
//////                        if(hasOne.getExtraType() != ExtraType.code) target.set(targetField, self.get(selfField));
////                        target.set(targetField, self.get(selfField));
////                        updateForRow(targetSeed, value, target);
////                        return;
////                    }
////
////                    if(targetId.equals(one.get(Const.ID))) { // 原来的数据
//////                        if(hasOne.getExtraType() != ExtraType.code) target.set(targetField, self.get(selfField));
////                        target.set(targetField, self.get(selfField));
////                        updateForRow(targetSeed, value, target);
////                        return;
////                    }
////
////                    removeOne(hasOne, one);
//////                    if(hasOne.getExtraType() != ExtraType.code) target.set(targetField, self.get(selfField));
////                    target.set(targetField, self.get(selfField));
////                    updateForRow(targetSeed, value, target);
//                }
//                case hasMany -> {
////                    HasManys hasMany = (HasManys) value.getProperty();
////                    Seed targetSeed = hasMany.targetSeed();
////                    String selfField = StrUtil.toCamelCase(hasMany.inferSelfColumn());
////                    String targetField = StrUtil.toCamelCase(hasMany.inferTargetColumn());
////                    String targetTableName = targetSeed.getTableName();
////
////                    Object targetObj = self.remove(fieldName);
////                    QueryCondition queryCondition = hasMany.getQueryCondition(self, null);
////                    List<Row> many = DbChain.table(targetTableName).where(queryCondition).list();
////                    if(targetObj == null) {
////                        removeMany(hasMany, many);
////                        return;
////                    }
////
////                    Collection<Row> target;
////                    if(targetObj.getClass().isArray()) {
////                        target = List.of((Row[]) targetObj);
////                    } else if(targetObj instanceof Collection<?>) {
////                        target = (Collection<Row>) targetObj;
////                    } else {
////                        throw new RuntimeException(String.format("不支持的类型【%s】", targetObj.getClass()));
////                    }
//
////                    List<Row> adding = target.stream()
////                        .filter(e -> e.get(Const.ID) == null)
////                        .peek(e -> {
////                            if(hasMany.hasCrossField()) e.set(targetField, self.get(selfField));
////                        }).toList();
////                    List<Row> adding = new ArrayList<>();
////                    for(Map<String, Object> map: target) {
////                        if(map.get(Const.ID) != null) continue;
////
////                        Row t = RowKit.toRow(map);
////                        t.getPrimaryKeys().add(RowKey.FLEX_ID);
//////                        if(hasMany.getExtraType() != ExtraType.code) t.set(targetField, self.get(selfField));
////                        t.set(targetField, self.get(selfField));
////                        adding.add(t);
////                    }
////                    SeedSave.saveBatch(targetSeed, value, adding);
////
////                    List<Object> oldIds = many.stream().map(e -> e.get(Const.ID)).toList();
////                    List<Row> updating = target.stream()
////                        .filter(e -> oldIds.contains(e.get(Const.ID)))
////                        .peek(e -> {
////                            if(hasMany.hasCrossField()) e.set(targetField, self.get(selfField));
////                        }).toList();
////                    List<Row> updating = new ArrayList<>();
////                    for(Map<String, Object> map: target) {
////                        if(!oldIds.contains(map.get(Const.ID))) continue;
////
////                        Row t = RowKit.toRow(map);
//////                        if(hasMany.getExtraType() != ExtraType.code) t.set(targetField, self.get(selfField));
////                        t.set(targetField, self.get(selfField));
////                        updating.add(t);
////                    }
////                    updateBatch(targetSeed, value, updating);
//
////                    List<Row> removing = target.stream()
////                        .filter(e -> e.get(Const.ID) != null && !oldIds.contains(e.get(Const.ID)))
////                        .toList();
////                    List<Row> removing = new ArrayList<>();
////                    for(Map<String, Object> map: target) {
////                        if(map.get(Const.ID) != null && !oldIds.contains(map.get(Const.ID))) removing.add(RowKit.toRow(map));
////                    }
////                    removeMany(hasMany, removing);
//                }
//                case habtm -> {
////                    Habtms habtm = (Habtms) value.getProperty();
////                    String through = habtm.throughTableName();
////                    String selfField = StrUtil.toCamelCase(habtm.inferSelfColumn());
////                    String targetField = StrUtil.toCamelCase(habtm.inferTargetColumn());
////                    String inferThroughSelfColumn = habtm.inferThroughSelfColumn();
////                    String inferThroughTargetColumn = habtm.inferThroughTargetColumn();
////                    String throughSelfField = StrUtil.toCamelCase(inferThroughSelfColumn);
////                    String throughTargetField = StrUtil.toCamelCase(inferThroughTargetColumn);
////                    Object targetObj = self.remove(fieldName);
////                    QueryCondition throughQueryCondition = habtm.getThroughQueryCondition(self, null);
////                    List<Row> throughs = DbChain.table(through).where(throughQueryCondition).list();
////                    List<Object> throughTargetValues = throughs.stream().map(e -> e.get(throughTargetField)).toList();
////
////                    if(targetObj == null) {
////                        removeHabtm(habtm, throughs);
////                        return;
////                    }
////
////                    Collection<Row> target;
////                    if(targetObj.getClass().isArray()) {
////                        target = List.of((Row[]) targetObj);
////                    } else if(targetObj instanceof Collection<?>) {
////                        target = (Collection<Row>) targetObj;
////                    } else {
////                        throw new RuntimeException(String.format("不支持的类型【%s】", targetObj.getClass()));
////                    }
//
////                    if(habtm.getExtraType() != ExtraType.code) {
////                        List<Row> adding = new ArrayList<>();
////                        for(Row row: target) {
////                            Object targetValue = row.get(targetField);
////                            if(throughTargetValues.contains(targetValue)) continue;
////
////                            Row ret = Row.ofKey(RowKey.FLEX_ID);
////                            ret.set(throughSelfField, self.get(selfField));
////                            ret.set(throughTargetField, row.get(targetField));
////                            adding.add(ret);
////                        }
////                        if(!adding.isEmpty()) Db.insertBatch(through, adding);
////                    }
////                    List<Row> adding = new ArrayList<>();
////                    for(Row row: target) {
////                        Object targetValue = row.get(targetField);
////                        if(throughTargetValues.contains(targetValue)) continue;
////
////                        Row ret = Row.ofKey(RowKey.FLEX_ID);
////                        ret.set(throughSelfField, self.get(selfField));
////                        ret.set(throughTargetField, row.get(targetField));
////                        adding.add(ret);
////                    }
////                    if(!adding.isEmpty()) Db.insertBatch(through, adding);
//
////                    if(habtm.getExtraType() != ExtraType.code) {
////                        List<Object> targetValues = target.stream().map(e -> e.get(throughTargetField)).toList();
////                        List<Row> removing = new ArrayList<>();
////                        for(Row row: throughs) {
////                            Object throughTargetValue = row.get(throughTargetField);
////                            if(targetValues.contains(throughTargetValue)) continue;
////
////                            removing.add(row);
////                        }
////                        removeHabtm(habtm, removing);
////                    }
////                    List<Object> targetValues = target.stream().map(e -> e.get(throughTargetField)).toList();
////                    List<Row> removing = new ArrayList<>();
////                    for(Row row: throughs) {
////                        Object throughTargetValue = row.get(throughTargetField);
////                        if(targetValues.contains(throughTargetValue)) continue;
////
////                        removing.add(row);
////                    }
////                    removeHabtm(habtm, removing);
//                }
//            }
//        }
//
//        Row row = RowKit.toUnderlineKeys(self);
//        row.getPrimaryKeys().add(RowKey.FLEX_ID);
//        Db.updateById(seed.getTableName(), row);
//    }
//
//    public static <T> void updateForObject(Seed seed, Map<String, Declared> declareds, T self) {
//        for(Map.Entry<String, Declared> entry: declareds.entrySet()) {
//            String crossOrColumn = entry.getKey();
//            String fieldName = StrUtil.toCamelCase(crossOrColumn);
//            Declared value = entry.getValue();
//            PropertyType propertyType = value.getType();
//            switch (propertyType) {
//                case belongsTo -> {
//                    BelongsTos belongsTo = (BelongsTos) value.getProperty();
//                    Object target = RowKit.getFieldValue(self, fieldName);
////                    if(belongsTo.getExtraType() != ExtraType.code) {
////                        String selfField = StrUtil.toCamelCase(belongsTo.inferSelfColumn());
////                        String targetField = StrUtil.toCamelCase(belongsTo.inferTargetColumn());
////                        RowKit.setSelfValue(self, selfField, target == null ? null : RowKit.getFieldValue(target, targetField));
////                    }
//                    String selfField = StrUtil.toCamelCase(belongsTo.inferSelfColumn());
//                    String targetField = StrUtil.toCamelCase(belongsTo.inferTargetColumn());
//                    RowKit.setSelfValue(self, selfField, target == null ? null : RowKit.getFieldValue(target, targetField));
//                }
//                case hasOne -> {
////                    HasOnes hasOne = (HasOnes) value.getProperty();
////                    Seed targetSeed = hasOne.targetSeed();
////                    String targetTableName = targetSeed.getTableName();
////                    String inferSelfColumn = hasOne.inferSelfColumn();
////                    String inferTargetColumn = hasOne.inferTargetColumn();
////                    String selfField = StrUtil.toCamelCase(inferSelfColumn);
////                    String targetField = StrUtil.toCamelCase(inferTargetColumn);
////                    Object target = RowKit.getFieldValue(self, fieldName);
////
////                    QueryCondition queryCondition = hasOne.getQueryCondition(self, null);
////                    Row one = DbChain.table(targetTableName).where(queryCondition).one();
////                    if(target == null) {
////                        removeOne(hasOne, one);
////                        return;
////                    }
////
////                    Object targetId = RowKit.getFieldValue(target, Const.ID);
////                    if(targetId == null) { // 新增加的数据
////                        removeOne(hasOne, one);
////
//////                        if(hasOne.getExtraType() != ExtraType.code) {
//////                            RowKit.setFieldValue(target, targetField, RowKit.getFieldValue(self, selfField));
//////                        }
////                        RowKit.setFieldValue(target, targetField, RowKit.getFieldValue(self, selfField));
////                        SeedSave.save(targetSeed, value, target);
////                        return;
////                    }
////
////                    if(one == null) {
//////                        if(hasOne.getExtraType() != ExtraType.code) {
//////                            RowKit.setFieldValue(target, targetField, RowKit.getFieldValue(self, selfField));
//////                        }
////                        RowKit.setFieldValue(target, targetField, RowKit.getFieldValue(self, selfField));
////                        updateForObject(targetSeed, value, target);
////                        return;
////                    }
////
////                    if(targetId.equals(one.get(Const.ID))) { // 原来的数据
//////                        if(hasOne.getExtraType() != ExtraType.code) {
//////                            RowKit.setFieldValue(target, targetField, RowKit.getFieldValue(self, selfField));
//////                        }
////                        RowKit.setFieldValue(target, targetField, RowKit.getFieldValue(self, selfField));
////                        updateForObject(targetSeed, value, target);
////                        return;
////                    }
////
////                    removeOne(hasOne, one);
//////                    if(hasOne.getExtraType() != ExtraType.code) {
//////                        RowKit.setFieldValue(target, targetField, RowKit.getFieldValue(self, selfField));
//////                    }
////                    RowKit.setFieldValue(target, targetField, RowKit.getFieldValue(self, selfField));
////                    updateForObject(targetSeed, value, target);
//                }
//                case hasMany -> {
////                    HasManys hasMany = (HasManys) value.getProperty();
////                    Seed targetSeed = hasMany.targetSeed();
////                    String selfField = StrUtil.toCamelCase(hasMany.inferSelfColumn());
////                    String targetField = StrUtil.toCamelCase(hasMany.inferTargetColumn());
////                    String targetTableName = targetSeed.getTableName();
////
////                    Object targetObj = RowKit.getFieldValue(self, fieldName);
////                    QueryCondition queryCondition = hasMany.getQueryCondition(self, null);
////                    List<Row> many = DbChain.table(targetTableName).where(queryCondition).list();
////                    if(targetObj == null) {
////                        removeMany(hasMany, many);
////                        return;
////                    }
////
////                    Collection<Row> target;
////                    if(targetObj.getClass().isArray()) {
////                        target = List.of((Row[]) targetObj);
////                    } else if(targetObj instanceof Collection<?>) {
////                        target = (Collection<Row>) targetObj;
////                    } else {
////                        throw new RuntimeException(String.format("不支持的类型【%s】", targetObj.getClass()));
////                    }
////
////                    List<Row> adding = target.stream()
////                        .filter(e -> e.get(Const.ID) == null)
////                        .peek(e -> {
//////                            if(hasMany.getExtraType() != ExtraType.code) {
//////                                RowKit.setFieldValue(e, targetField, RowKit.getFieldValue(self, selfField));
//////                            }
////                            RowKit.setFieldValue(e, targetField, RowKit.getFieldValue(self, selfField));
////                        }).toList();
////                    SeedSave.saveBatch(targetSeed, value, adding);
////
////                    List<Object> oldIds = many.stream().map(e -> e.get(Const.ID)).toList();
////                    List<Row> updating = target.stream()
////                        .filter(e -> oldIds.contains(e.get(Const.ID)))
////                        .peek(e -> {
//////                            if(hasMany.getExtraType() != ExtraType.code) {
//////                                RowKit.setFieldValue(e, targetField, RowKit.getFieldValue(self, selfField));
//////                            }
////                            RowKit.setFieldValue(e, targetField, RowKit.getFieldValue(self, selfField));
////                        }).toList();
////                    updateBatch(targetSeed, value, updating);
////
////                    List<Row> removing = target.stream()
////                        .filter(e -> e.get(Const.ID) != null && !oldIds.contains(e.get(Const.ID)))
////                        .toList();
////                    removeMany(hasMany, removing);
//                }
//                case habtm -> {
////                    Habtms habtm = (Habtms) value.getProperty();
////                    String through = habtm.throughTableName();
////                    String selfField = StrUtil.toCamelCase(habtm.inferSelfColumn());
////                    String targetField = StrUtil.toCamelCase(habtm.inferTargetColumn());
////                    String inferThroughSelfColumn = habtm.inferThroughSelfColumn();
////                    String inferThroughTargetColumn = habtm.inferThroughTargetColumn();
////                    String throughSelfField = StrUtil.toCamelCase(inferThroughSelfColumn);
////                    String throughTargetField = StrUtil.toCamelCase(inferThroughTargetColumn);
////                    Object targetObj = RowKit.getFieldValue(self, fieldName);
////                    QueryCondition throughQueryCondition = habtm.getThroughQueryCondition(self, null);
////                    List<Row> throughs = DbChain.table(through).where(throughQueryCondition).list();
////                    List<Object> throughTargetValues = throughs.stream().map(e -> e.get(throughTargetField)).toList();
////
////                    if(targetObj == null) {
////                        removeHabtm(habtm, throughs);
////                        return;
////                    }
////
////                    Collection<Row> target;
////                    if(targetObj.getClass().isArray()) {
////                        target = List.of((Row[]) targetObj);
////                    } else if(targetObj instanceof Collection<?>) {
////                        target = (Collection<Row>) targetObj;
////                    } else {
////                        throw new RuntimeException(String.format("不支持的类型【%s】", targetObj.getClass()));
////                    }
////
//////                    if(habtm.getExtraType() != ExtraType.code) {
//////                        List<Row> adding = new ArrayList<>();
//////                        for(Row row: target) {
//////                            Object targetValue = row.get(targetField);
//////                            if(throughTargetValues.contains(targetValue)) continue;
//////
//////                            Row ret = Row.ofKey(RowKey.FLEX_ID);
//////                            ret.set(throughSelfField, RowKit.getFieldValue(self, selfField));
//////                            ret.set(throughTargetField, row.get(targetField));
//////                            adding.add(ret);
//////                        }
//////                        if(!adding.isEmpty()) Db.insertBatch(through, adding);
//////                    }
////                    List<Row> adding = new ArrayList<>();
////                    for(Row row: target) {
////                        Object targetValue = row.get(targetField);
////                        if(throughTargetValues.contains(targetValue)) continue;
////
////                        Row ret = Row.ofKey(RowKey.FLEX_ID);
////                        ret.set(throughSelfField, RowKit.getFieldValue(self, selfField));
////                        ret.set(throughTargetField, row.get(targetField));
////                        adding.add(ret);
////                    }
////                    if(!adding.isEmpty()) Db.insertBatch(through, adding);
////
//////                    if(habtm.getExtraType() != ExtraType.code) {
//////                        List<Object> targetValues = target.stream().map(e -> e.get(throughTargetField)).toList();
//////                        List<Row> removing = new ArrayList<>();
//////                        for(Row row: throughs) {
//////                            Object throughTargetValue = row.get(throughTargetField);
//////                            if(targetValues.contains(throughTargetValue)) continue;
//////
//////                            removing.add(row);
//////                        }
//////                        removeHabtm(habtm, removing);
//////                    }
////                    List<Object> targetValues = target.stream().map(e -> e.get(throughTargetField)).toList();
////                    List<Row> removing = new ArrayList<>();
////                    for(Row row: throughs) {
////                        Object throughTargetValue = row.get(throughTargetField);
////                        if(targetValues.contains(throughTargetValue)) continue;
////
////                        removing.add(row);
////                    }
////                    removeHabtm(habtm, removing);
//                }
//            }
//        }
//
//        BaseMapper<T> baseMapper = Mappers.ofEntityClass((Class<T>) self.getClass());
//        baseMapper.update(self);
//    }
//
//    public static <T> T getValidData(Seed seed, Map<String, Declared> declareds, T self) {
//        T ret = self instanceof Row ? (T) Row.ofKey(RowKey.FLEX_ID) : (T) ReflectUtil.newInstance(self.getClass());
//        for(Map.Entry<String, Declared> entry: declareds.entrySet()) {
//            String crossOrColumn = entry.getKey();
//            String fieldName = StrUtil.toCamelCase(crossOrColumn);
//            Declared value = entry.getValue();
//            PropertyType propertyType = value.getType();
//            switch (propertyType) {
//                case none, asterisk -> {
//                    Map<String, Column> columns = SeedKit.getColumns(seed);
//                    for (Column column: columns.values()) {
//                        SeedValidator.validate(seed, column, self);
//                        fieldName = StrUtil.toCamelCase(column.getName());
//                        Object fieldValue = RowKit.getSelfValue(self, fieldName);
//                        RowKit.setSelfValue(ret, fieldName, fieldValue);
//                    }
//                }
//                case column -> {
//                    Column column = (Column) value.getProperty();
//                    SeedValidator.validate(seed, column, self);
//                    Object fieldValue = RowKit.getFieldValue(self, fieldName);
//                    RowKit.setSelfValue(ret, fieldName, fieldValue);
//                }
//                case belongsTo -> {
//                    Relation relation = (Relation) value.getProperty();
//                    Object target = RowKit.getSelfValue(self, fieldName);
//                    if(target != null) {
////                        if(relation.getExtraType() != ExtraType.code) {
////                            String selfField = StrUtil.toCamelCase(relation.inferSelfColumn());
////                            String targetField = StrUtil.toCamelCase(relation.inferTargetColumn());
////                            RowKit.setSelfValue(ret, selfField, RowKit.getSelfValue(target, targetField));
////                        }
//                        String selfField = StrUtil.toCamelCase(relation.inferSelfColumn());
//                        String targetField = StrUtil.toCamelCase(relation.inferTargetColumn());
//                        RowKit.setSelfValue(ret, selfField, RowKit.getSelfValue(target, targetField));
////                        if(relation.getCondition() == null) {
////                            String selfField = StrUtil.toCamelCase(relation.inferSelfColumn());
////                            String targetField = StrUtil.toCamelCase(relation.inferTargetColumn());
////                            RowKit.setSelfValue(ret, selfField, RowKit.getSelfValue(target, targetField));
////                        } else {
////                            String selfColumn = relation.getSelfColumn();
////                            String targetColumn = relation.getTargetColumn();
////                            if(StrUtil.isNotBlank(selfColumn) || StrUtil.isNotBlank(targetColumn)) {
////                                String selfField = StrUtil.toCamelCase(relation.inferSelfColumn());
////                                String targetField = StrUtil.toCamelCase(relation.inferTargetColumn());
////                                RowKit.setSelfValue(ret, selfField, RowKit.getSelfValue(target, targetField));
////                            }
////                        }
//                    }
//                }
//                case hasOne -> {
//                    Relation relation = (Relation) value.getProperty();
//                    Seed targetSeed = relation.targetSeed();
//                    Object oldFieldValue = RowKit.getSelfValue(self, fieldName);
//                    if(oldFieldValue == null) {
//                        RowKit.setSelfValue(ret, fieldName, null);
//                    } else {
//                        Object fieldValue = getValidData(targetSeed, value, oldFieldValue);
//                        RowKit.setSelfValue(ret, fieldName, fieldValue);
//                    }
//                }
//                case hasMany -> {
//                    Relation relation = (Relation) value.getProperty();
//                    Seed targetSeed = relation.targetSeed();
//                    Object oldFieldValue = RowKit.getSelfValue(self, fieldName);
//                    Object fieldValue;
//                    if(oldFieldValue.getClass().isArray()) {
//                        fieldValue = getValidArray(targetSeed, value, (Object[]) oldFieldValue);
//                    } else if(oldFieldValue instanceof Set<?>) {
//                        fieldValue = getValidSet(targetSeed, value, (Set<Object>) oldFieldValue);
//                    } else if(oldFieldValue instanceof List<?>) {
//                        fieldValue = getValidList(targetSeed, value, (List<Object>) oldFieldValue);
//                    } else {
//                        throw new RuntimeException(String.format("不支持的类型【%s】", oldFieldValue.getClass()));
//                    }
//                    RowKit.setSelfValue(ret, fieldName, fieldValue);
//                }
//                default -> RowKit.setSelfValue(ret, fieldName, RowKit.getSelfValue(self, fieldName));
//            }
//        }
//
//        return ret;
//    }
//
//    public static <T> T[] getValidArray(Seed seed, Map<String, Declared> declareds, T[] data) {
//        List<T> ret = new ArrayList<>();
//        for(T t: data) ret.add(getValidData(seed, declareds, t));
//
//        return (T[]) ret.toArray();
//    }
//
//    public static <T> Set<T> getValidSet(Seed seed, Map<String, Declared> declareds, Set<T> data) {
//        Set<T> ret = new HashSet<>();
//        for(T t: data) ret.add(getValidData(seed, declareds, t));
//
//        return ret;
//    }
//
//    public static <T> List<T> getValidList(Seed seed, Map<String, Declared> declareds, List<T> data) {
//        List<T> ret = new ArrayList<>();
//        for(T t: data) ret.add(getValidData(seed, declareds, t));
//
//        return ret;
//    }
//
////    private static <T> void validate(Seed seed, Column column, T data) {
////        String tableName = seed.getTableName();
////        String columnName = column.getName();
////        String label = StrUtil.isBlank(column.getLabel()) ? columnName : column.getLabel();
////        ColumnType columnType = column.getType();
////        String fieldName = StrUtil.toCamelCase(columnName);
////        Object id = RowKit.getSelfValue(data, Const.ID);
////        Object value = RowKit.getSelfValue(data, fieldName);
////
////        Boolean required = column.getRequired();
////        Boolean unique = column.getUnique();
////        String min = (String) column.getMin();
////        String max = (String) column.getMax();
////        Integer length = column.getLength();
////
////        if(required != null && required && StrUtil.isBlank((String) value)) throw new RuntimeException(String.format("【%s】不能为空", label));
////
////        if(unique != null && unique) {
////            int count = (int) DbChain.table(tableName)
////                .select(QueryMethods.count())
////                .where(new QueryColumn(Const.ID).ne(id).and(new QueryColumn(columnName).eq(value)))
////                .obj();
////            if(count > 0) throw new RuntimeException(String.format("%s【%s】已存在", label, value));
////        }
////
////        switch (columnType) {
////            case CHAR -> {
////                if(Const.ID.equals(columnName)) return;
////                if(value == null) return;
////                String val = value instanceof Long v ? Long.toString(v) : (String) value;
////                int len = val.length();
////                if(len != length) throw new RuntimeException(String.format("%s长度必需等于【%s】", label, length));
////            }
////            case TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT -> {
//////                if(StrUtil.isNotBlank((CharSequence) value)) {
//////                    long v = Long.parseLong((String) value);
//////                    if(min != null) {
//////                        long mi = Long.parseLong(min);
//////                        if(v < mi) throw new RuntimeException(String.format("%s不能小于【%s】", label, mi));
//////                    }
//////
//////                    if(max != null) {
//////                        long ma = Long.parseLong(max);
//////                        if(v > ma) throw new RuntimeException(String.format("%s不能大于【%s】", label, ma));
//////                    }
//////                }
////            }
////            case DOUBLE, FLOAT -> {
////                double v = Double.parseDouble((String) value);
////                if(min != null) {
////                    double mi = Double.parseDouble(min);
////                    if(v < mi) throw new RuntimeException(String.format("%s不能小于【%s】", label, mi));
////                }
////
////                if(max != null) {
////                    double ma = Double.parseDouble(max);
////                    if(v > ma) throw new RuntimeException(String.format("%s不能大于【%s】", label, ma));
////                }
////            }
////            case DECIMAL -> {
////                BigDecimal v = new BigDecimal((String) value);
////                if(min != null) {
////                    BigDecimal mi = new BigDecimal(min);
////                    if(v.compareTo(mi) < 0) throw new RuntimeException(String.format("%s不能小于【%s】", label, mi));
////                }
////
////                if(max != null) {
////                    BigDecimal ma = new BigDecimal(max);
////                    if(v.compareTo(ma) < 0) throw new RuntimeException(String.format("%s不能大于【%s】", label, ma));
////                }
////            }
////            default -> {
////                if(value instanceof YesNo) return;
////
////                int len = StrUtil.isBlank((String) value) ? 0 : ((String) value).length();
////                if(min != null) {
////                    int mi = Integer.parseInt(min);
////                    if(len < mi) throw new RuntimeException(String.format("%s长度不能小于【%s】", label, mi));
////                }
////
////                if(max != null) {
////                    int ma = Integer.parseInt(max);
////                    if(len > ma) throw new RuntimeException(String.format("%s长度不能大于【%s】", label, ma));
////                }
////            }
////        }
////    }
//
//    /**
//     * 是否只存在一级数据
//     * @param declareds 数据申明
//     * @return bool
//     */
//    private static boolean isPlain(Map<String, Declared> declareds) {
//        for (Declared declared: declareds.values()) {
//            if (!declared.getType().equals(PropertyType.column)) return false;
//        }
//
//        return true;
//    }
//
//    public static void removeOne(HasOnes hasOne, Row one) {
//        if(one == null) return;
//
//        Object oneId = one.get(Const.ID);
//        Cascade cascade = hasOne.getCascade();
//        Seed targetSeed = hasOne.targetSeed();
//        String targetTableName = targetSeed.getTableName();
//        String inferTargetColumn = hasOne.inferTargetColumn();
//        if(cascade == Cascade.force) {
//            SeedRemove.remove(targetSeed, oneId);
//        } else {
//            DbChain.table(targetTableName).set(inferTargetColumn, null).where(new QueryColumn(Const.ID).eq(oneId)).update();
//        }
//    }
//
//    private static void removeMany(HasManys hasMany, List<Row> many) {
//        if (many == null || many.isEmpty()) return;
//
//        List<Object> manyIds = many.stream().map(e -> e.get(Const.ID)).toList();
//        Cascade cascade = hasMany.getCascade();
//        Seed targetSeed = hasMany.targetSeed();
//        String targetTableName = targetSeed.getTableName();
//        String inferTargetColumn = hasMany.inferTargetColumn();
//        if(cascade == Cascade.force) {
//            SeedRemove.removeBatch(targetSeed, manyIds);
//        } else {
//            DbChain.table(targetTableName).set(inferTargetColumn, null).where(new QueryColumn(Const.ID).in(manyIds)).update();
//        }
//    }
//
//    private static void removeHabtm(Habtms habtm, List<Row> throughs) {
//        if(throughs.isEmpty()) return;
//
//        List<Object> throughIds = throughs.stream().map(e -> e.get(Const.ID)).toList();
//        Cascade cascade = habtm.getCascade();
//        String through = habtm.throughTableName();
//        String inferThroughSelfColumn = habtm.inferThroughSelfColumn();
//        String inferThroughTargetColumn = habtm.inferThroughTargetColumn();
//        if(cascade == Cascade.force) {
//            Db.deleteByCondition(through, new QueryColumn(Const.ID).in(throughIds));
//        } else {
//            DbChain.table(through)
//                .set(inferThroughSelfColumn, null)
//                .set(inferThroughTargetColumn, null)
//                .where(new QueryColumn(Const.ID).in(throughIds))
//                .update();
//        }
//    }
}
